module cl {
	export abstract class ActionPerformer extends ActionDO {
		abstract accept() : void;
		abstract acceptOnce() : void;
		abstract duration() : number;
		abstract play(map : CampaignPage) : void;
	}

	export class ActionUtil {
		public static setAction(
				action : ActionPerformer,
				troopid : number,
				move_remain : number = -99,
				tid : number = -1,
				other_troopids : number[] = [],
				other_m_remain : number[] = [],
				tick : number = -1) : ActionPerformer {
			action.troopid = troopid;
			action.move_remain = move_remain != -99 ? move_remain : Campaign.troop[troopid].move_remain;
			action.tid = tid >= 0 ? tid : Campaign.troop[troopid].tid;
			action.other_troopids = other_troopids;
			action.other_m_remain = other_m_remain;
			action.tick = tick >= 0 ? tick : Campaign.time_ref.current_step;
			return action;
		}

		public static createActionPerformer(action : ActionDO) : ActionDO {
			let params = JSON.parse(action.paramVals) as any[];
			switch (action.type) {
				case 1:
					return Util.newInstance(MoveAction, params);
			}
			return action;
		}

		public static getParamJSON(action : ActionDO) : Object {
			let vals = JSON.parse(action.paramVals) as string[];
			let keys = JSON.parse(action.paramKeys) as any[];
			let obj = {};
			for (let i = 0; i < keys.length; i++) {
				obj[keys[i]] = vals[i];
			}
			return obj;
		}

		public static acceptActions(actions : ActionPerformer[]) : void {
			for (let action of actions) {
				action.accept();
			}
		}
	}

	export class ActionPlayer {
		public constructor(public map : CampaignPage, public actions : ActionPerformer[], public cb : (()=>void), public cbThis : any) {
		}

		private actionid : number;

		public playAndAcceptActions() : void {
			this.actionid = -1;

			let curtain = new CurtainMask("REPORT - Round " + (Campaign.time_ref.current_step + 1) + "", "", 0x004466);
			this.map.addChild(curtain);
			setTimeout( () => {
				this.playAndAcceptAction();
			}, curtain.fadeInOutTimeout() );
		}

		private playAndAcceptAction() : void {
			do {
				this.actionid++;
			} while (this.actionid < this.actions.length && this.actions[this.actionid].duration() == 0);

			if (this.actionid >= this.actions.length) {
				this.cb.call(this.cbThis);
			} else {
				this.actions[this.actionid].play(this.map);
				this.actions[this.actionid].accept();
				setTimeout(this.playAndAcceptAction.bind(this), this.actions[this.actionid].duration());
			}
		}
	}
}